package com.fresh.bus.chat.business;

import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;

import javax.annotation.Resource;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.BoundHashOperations;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.data.redis.support.atomic.RedisAtomicLong;
import org.springframework.data.redis.support.collections.DefaultRedisList;
import org.springframework.data.redis.support.collections.DefaultRedisMap;
import org.springframework.data.redis.support.collections.DefaultRedisSet;
import org.springframework.data.redis.support.collections.RedisList;
import org.springframework.data.redis.support.collections.RedisMap;
import org.springframework.data.redis.support.collections.RedisSet;

import com.fresh.bus.chat.domain.BusLine;
import com.fresh.bus.chat.persist.SystemDao;
import com.fresh.bus.chat.persist.ZhiFeiJiDao;

@Component
public class SystemConfig implements InitializingBean {
	private static final Logger log = LoggerFactory
			.getLogger(SystemConfig.class);
	@Resource
	private SystemDao dao;

	private final StringRedisTemplate template;

	private RedisSet<String> cities;
	private RedisSet<String> buses;
	private RedisSet<String> stops;

	public RedisSet<String> rooms;
	
	private RedisMap<String, String> nameMap;
	private Map<Integer, Map<String, Object>> levelMap;
	private Map<Integer, Map<String, Object>> assoMap;
	
	@Autowired
	public SystemConfig(StringRedisTemplate template) {
		this.template = template;

		nameMap = new DefaultRedisMap<String, String>(KeyUtils.names(),
				template);

		cities = new DefaultRedisSet<String>(KeyUtils.cities(), template);
		buses = new DefaultRedisSet<String>(KeyUtils.lines(), template);
		stops = new DefaultRedisSet<String>(KeyUtils.stations(), template);
		rooms = new DefaultRedisSet<String>(KeyUtils.rooms(), template);
	}

	private void initCities() throws Exception {
		this.cities.addAll((Collection<? extends String>) dao.getAllCities());

		for (String id : cities) {
			Map<String, String> city = (Map<String, String>) dao.getCity(id);
			String cid = KeyUtils.cid(id);
			BoundHashOperations<String, String, String> ops = template
					.boundHashOps(cid);
			for (Map.Entry<String, String> entry : city.entrySet()) {
				ops.put(entry.getKey(), String.valueOf(entry.getValue()));
			}
		}
	}

	private void initBuses() throws Exception {
		this.buses.addAll((Collection<? extends String>) dao.getAllLines());

		for (String id : buses) {
			BusLine line = (BusLine) dao.getLine(id);
			String lid = KeyUtils.lid(id);
			BoundHashOperations<String, String, String> ops = template
					.boundHashOps(lid);
			ops.put("name", line.getName());
			ops.put("id", id);

			nameMap.put(KeyUtils.line(line.getName()), lid);
			StringBuffer stations = new StringBuffer();

			List<Integer> list = line.getStations();
			int len = list.size();

			for (int i = 0; i < len; i++) {
				String s = String.valueOf(list.get(i));
				template.boundListOps(KeyUtils.stations(id)).rightPush(s);
				template.boundListOps(KeyUtils.lines(s)).rightPush(id);

				String sName = (String) template.boundHashOps(KeyUtils.sid(s))
						.get("name");
				stations.append(sName);
				if (i < len - 1) {
					stations.append(",");
				}
			}

			ops.put("stations", stations.toString());
		}
	}

	private void initStops() throws Exception {
		this.stops.addAll((Collection<? extends String>) dao.getAllStations());
		for (String id : stops) {
			Map<String, String> station = (Map<String, String>) dao
					.getStation(id);
			String sid = KeyUtils.sid(id);

			BoundHashOperations<String, String, String> ops = template
					.boundHashOps(sid);
			for (Map.Entry<String, String> entry : station.entrySet()) {
				ops.put(entry.getKey(), String.valueOf(entry.getValue()));
			}

			String name = ops.get("name");
			nameMap.put(KeyUtils.station(name), sid);
		}
	}

	private void initRooms() throws Exception {
		this.rooms.addAll((Collection<? extends String>) dao.getAllRooms());

		for (String id : rooms) {
			Map<String, String> room = (Map<String, String>) dao.getRoom(id);
			String rid = KeyUtils.rid(id);

			BoundHashOperations<String, String, String> ops = template
					.boundHashOps(rid);
			// ops.putAll(room);
			for (Map.Entry<String, String> entry : room.entrySet()) {
				ops.put(entry.getKey(), String.valueOf(entry.getValue()));
			}
			
			ops.put("talker", "0");
			ops.put("femaleNum", "0");
			ops.put("maleNum", "0");

			String sid = String.valueOf(ops.get("station"));
			template.boundListOps(KeyUtils.rooms(sid)).rightPush(id);
			String type = ops.get("type");
			if (type.equals("0")) {
				template.boundHashOps(KeyUtils.sid(sid)).put("room", id);
			}
		}
	}

	
	@Override
	public void afterPropertiesSet() {
		try {
			long start = System.currentTimeMillis();
			this.initCities();
			this.initStops();
			this.initBuses();
			this.initRooms();
			this.initLevelStatic();
			this.initAssoStatic();

			log.info("Finish data inital "
					+ (System.currentTimeMillis() - start) + "ms");
		} catch (Exception e) {
			log.error("", e);
		}
	}

	private void initLevelStatic() {
		levelMap = new HashMap<Integer, Map<String, Object>>();
		List<Map<String, Object>> data = dao.getLevelStatic();
		Integer id;

		for (Map<String, Object> m : data) {
			id = (Integer) m.get("id");
			levelMap.put(id, m);
		}
	}
	
	public  Map<String, Object> findLevel(Integer id) {
		return levelMap.get(id);
	}
	
	private void initAssoStatic() {
		assoMap = new HashMap<Integer, Map<String, Object>>();
		List<Map<String, Object>> data = dao.getAssoStatic();
		Integer id;

		for (Map<String, Object> m : data) {
			id = (Integer) m.get("id");
			assoMap.put(id, m);
		}
	}
	
	public  Map<String, Object> findAsso(Integer id) {
		return assoMap.get(id);
	}	

	public String findSid(String name) {
		return nameMap.get(KeyUtils.station(name));
	}

	public String findLid(String name) {
		return nameMap.get(KeyUtils.line(name));
	}

}
